package com.whmskj.xjlhsc.service.impl;

import java.time.LocalDateTime;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.whmskj.xjlhsc.entity.JsdInfo;
import com.whmskj.xjlhsc.entity.Sb02EquipmentCounterAccount;
import com.whmskj.xjlhsc.enums.ScEnums.SC_PROCESS_TABLE_MAPPING;
import com.whmskj.xjlhsc.exception.BusinessException;
import com.whmskj.xjlhsc.exception.ExceptionText;
import com.whmskj.xjlhsc.jitapi.mapper.DeviceMapper;
import com.whmskj.xjlhsc.mapper.ScMapper;
import com.whmskj.xjlhsc.schedul.async.mapper.DbStateClassMapper;
import com.whmskj.xjlhsc.schedul.async.po.DbClsPowerStatistics;
import com.whmskj.xjlhsc.schedul.async.po.DbStateClass;
import com.whmskj.xjlhsc.schedul.async.service.DbClsPowerStatisticsService;
import com.whmskj.xjlhsc.service.MonitorService;
import com.whmskj.xjlhsc.service.Sb02EquipmentCounterAccountService;
import com.whmskj.xjlhsc.service.dto.FieldValue;
import com.whmskj.xjlhsc.service.dto.HumidificationRoomDto;
import com.whmskj.xjlhsc.service.dto.HumidificationRoomDto.HoverData;
import com.whmskj.xjlhsc.service.dto.RealInfoDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.whmskj.xjlhsc.service.dto.HumidificationRoomDto.*;

/**
 * @BelongsProject: XJLHSC
 * @BelongsPackage: com.whmskj.xjlhsc.service.impl
 * @Author: lk
 * @CreateTime: 2025-07-01
 * @Description: TODO
 * @Version: 1.0
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class MonitorServiceImpl implements MonitorService {

    private final Sb02EquipmentCounterAccountService deviceService;
    private final ScMapper scMapper;
    private final DeviceMapper deviceMapper;
    private final DbStateClassMapper dbStateClassMapper;
    private final DbClsPowerStatisticsService dbClsPowerStatisticsService;
    private static final String NO_DATA = "工序【%s】 实时数据表【%s】未查询到数据";


    @Override
    public RealInfoDto getDeviceRealTimeInfo(Integer deviceId) {
        Sb02EquipmentCounterAccount device = deviceService.getById(deviceId);
        if (StrUtil.isBlank(device.getMachineNumber())) throw new BusinessException(ExceptionText.DEVICE_ID_NOT_EXIST);
        String scTableAndIdTag = getScTableNameWithDevice(device);
        log.info("当前查询设备名称：{}", device.getDevicename() + "| 设备编号：" + device.getMachineNumber());
        String[] split = scTableAndIdTag.split("#");
        String tb = split[0];
        log.info("当前设备实时信息数采表：{}", tb);
        LinkedHashMap<String, Object> realData = scMapper.getDeviceRealTimeInfo(device.getMachineNumber(), tb, split[1], split[2]);

        if (ObjectUtil.isNull(realData)) throw new BusinessException(String.format(NO_DATA, device.getProcess(), tb));
        RealInfoDto realInfoDto = new RealInfoDto();
        realInfoDto.setRealTimeBox(realData.entrySet().stream().map(entry -> new FieldValue(entry.getKey(), entry.getValue(), getObtainFieldDesc(entry.getKey(), tb))).toList());
        realInfoDto.setRealTimeBox(realInfoDto.getRealTimeBox());
        return realInfoDto;
    }

    /**
     * 根据机台返回实时信息机台便
     *
     * @param device
     * @return
     */
    private String getScTableNameWithDevice(Sb02EquipmentCounterAccount device) {
        if (ObjectUtil.isNull(device)) throw new BusinessException(ExceptionText.DEVICE_NOT_EXIST);
        //工序定位数采表
        String process = device.getProcess();
        return SC_PROCESS_TABLE_MAPPING.getRealInfoTableNameByProcessName(process);
    }


    @Override
    public DbStateClass findDnInfo(Integer deviceId) {
        Integer dbId = deviceMapper.getDbIdByDeviceId(deviceId);
        if (ObjectUtil.isNull(dbId)) throw new BusinessException(ExceptionText.DEVICE_ID_REACTION_DB);
        DbStateClass dbStateClass = dbStateClassMapper.selectById(dbId);
        int day = 7;
        List<DbClsPowerStatistics> dbClsPowerStatistics = dbClsPowerStatisticsService.listByRangeWithDbId(day, dbId);
        Map<String, List<DbClsPowerStatistics>> collect = dbClsPowerStatistics.stream().collect(Collectors.groupingBy(DbClsPowerStatistics::getDateYmd));
        List<Map<String, String>> historyPowerInfo = createHistoryPowerInfo(day);
        for (Map<String, String> map : historyPowerInfo) {
            String date = map.keySet().stream().findFirst().get();
            List<DbClsPowerStatistics> dbClsPowerStatisticsList = collect.get(date);
            if (CollectionUtil.isNotEmpty(dbClsPowerStatisticsList)) {
                map.put(date, dbClsPowerStatisticsList.get(0).getTotalUse());
            }
        }
        dbStateClass.setHistoryPowerInfo(historyPowerInfo);
        return dbStateClass;

    }

    private List<Map<String, String>> createHistoryPowerInfo(Integer day) {
        LocalDate end = LocalDate.now();
        LocalDate start = end.minusDays(day);
        List<Map<String, String>> historyPowerInfo = new ArrayList<>();
        while (!start.isAfter(end)) {
            historyPowerInfo.add(MapUtil.builder(start.toString(), "0").build());
            start = start.plusDays(1);
        }
        return historyPowerInfo;
    }


    @Override
    public HumidificationRoomDto getHumidificationRoomRealData(String area) {
        List<JsdInfo> jsdInfos = scMapper.getHumidificationRoomRealData(area);
        HumidificationRoomDto resp = new HumidificationRoomDto();
        //悬浮数据
        HoverData hoverData = new HoverData();
        hoverData.setArea(area);
        hoverData.setProdLines(jsdInfos.stream().map(JsdInfo::getProdLineNo).toList());
        hoverData.setHdCount(jsdInfos.stream().mapToInt(JsdInfo::getTotal).sum());
        hoverData.setGteSeven(jsdInfos.stream().mapToInt(JsdInfo::getGteSeven).sum());
        hoverData.setLtSeven(jsdInfos.stream().mapToInt(JsdInfo::getLtSeven).sum());
        hoverData.setRcTime(jsdInfos.get(0).getRcTime());
        resp.setHoverData(hoverData);

        resp.setXAxis(jsdInfos.stream().map(cur -> cur.getProdLineNo() + "线").toList());
        List<Item> series = new ArrayList<>();
        series.add(new Item(">=700", jsdInfos.stream().map(JsdInfo::getGteSeven).toList()));
        series.add(new Item("<700", jsdInfos.stream().map(JsdInfo::getLtSeven).toList()));
        resp.setSeries(series);

        resp.setTableData(jsdInfos);

        return resp;
    }
}
